home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume16 / mtf / part01 next >
Encoding:
Internet Message Format  |  1991-02-02  |  20.4 KB

  1. From: goer@midway.uchicago.edu (Richard L. Goerwitz)
  2. Newsgroups: comp.sources.misc
  3. Subject: v16i085:  mtf - Map tar filenames, Part01/02
  4. Message-ID: <1991Jan29.012143.21569@sparky.IMD.Sterling.COM>
  5. Date: 29 Jan 91 01:21:43 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: 5d9f6bcf 21d03491 c3363fc3 4c90c7a2
  8.  
  9. Submitted-by: goer@midway.uchicago.edu (Richard L. Goerwitz)
  10. Posting-number: Volume 16, Issue 85
  11. Archive-name: mtf/part01
  12.  
  13. Tar archives often come packed with filenames longer than 15 chars,
  14. and with source code that requires that the filenames be fully pre-
  15. served.  This utility, mtf, runs through the tar headers, finds all
  16. overlong filenames, renames them, renames them in any text files it
  17. finds, and then rewrites the tar header checksums.
  18.  
  19. -Richard
  20.  
  21. ---- Cut Here and feed the following to sh ----
  22. #!/bin/sh
  23. # This is a shell archive (produced by shar 3.49)
  24. # To extract the files from this archive, save it to a file, remove
  25. # everything above the "!/bin/sh" line above, and type "sh file_name".
  26. #
  27. # made 01/20/1991 23:34 UTC by goer@sophist.uchicago.edu
  28. # Source directory /u/richard/Mtf
  29. #
  30. # existing files will NOT be overwritten unless -c is specified
  31. # This format requires very little intelligence at unshar time.
  32. # "if test", "cat", "rm", "echo", "true", and "sed" may be needed.
  33. #
  34. # This is part 1 of a multipart archive                                    
  35. # do not concatenate these parts, unpack them in order with /bin/sh        
  36. #
  37. # This shar contains:
  38. # length  mode       name
  39. # ------ ---------- ------------------------------------------
  40. #  16721 -r--r--r-- mtf.icn
  41. #   3341 -rw-r--r-- README
  42. #    659 -rw-r--r-- Makefile.dist
  43. #
  44. if test -r _shar_seq_.tmp; then
  45.     echo 'Must unpack archives in sequence!'
  46.     echo Please unpack part `cat _shar_seq_.tmp` next
  47.     exit 1
  48. fi
  49. # ============= mtf.icn ==============
  50. if test -f 'mtf.icn' -a X"$1" != X"-c"; then
  51.     echo 'x - skipping mtf.icn (File already exists)'
  52.     rm -f _shar_wnt_.tmp
  53. else
  54. > _shar_wnt_.tmp
  55. echo 'x - extracting mtf.icn (Text)'
  56. sed 's/^X//' << 'SHAR_EOF' > 'mtf.icn' &&
  57. X#############################################################################
  58. X#
  59. X#    NAME:    mtf3.icn
  60. X#
  61. X#    TITLE:    map tar file
  62. X#
  63. X#    AUTHOR:    Richard Goerwitz
  64. X#
  65. X#    VERSION: 3.3
  66. X#
  67. X#############################################################################
  68. X#
  69. X#  This and future versions of mtf are hereby placed in the public domain -RLG
  70. X#
  71. X#############################################################################
  72. X#
  73. X#  PURPOSE: Maps 15+ char. filenames in a tar archive to 14 chars.
  74. X#  Handles both header blocks and the archive itself.  Mtf is intended
  75. X#  to facilitate installation of tar'd archives on systems subject to
  76. X#  the System V 14-character filename limit.
  77. X#
  78. X#  USAGE:  mtf inputfile [-r reportfile] [-e .extensions] [-x exceptions]
  79. X#
  80. X#  "Inputfile" is a tar archive.  "Reportfile" is file containing a
  81. X#  list of files already mapped by mtf in a previous run (used to
  82. X#  avoid clashes with filenames in use outside the current archive).
  83. X#  The -e switch precedes a list of filename .extensions which mtf is
  84. X#  supposed to leave unscathed by the mapping process
  85. X#  (single-character extensions such as .c and .o are automatically
  86. X#  preserved; -e allows the user to specify additional extensions,
  87. X#  such as .pxl, .cpi, and .icn).  The final switch, -x, precedes a
  88. X#  list of strings which should not be mapped at all.  Use this switch
  89. X#  if, say, you have a C file with a structure.field combination such
  90. X#  as "thisisveryverybig.hashptr" in an archive that contains a file
  91. X#  called "thisisveryverybig.h," and you want to avoid mapping that
  92. X#  portion of the struct name which matches the name of the overlong
  93. X#  file (to wit, "mtf inputfile -x thisisveryverybig.hashptr").  To
  94. X#  prevent mapping of any string (including overlong filenames) begin-
  95. X#  ning, say, with "thisisvery," use "mtf inputfile -x thisisvery."
  96. X#  Be careful with this option, or you might end up defeating the
  97. X#  whole point of using mtf in the first place.
  98. X#
  99. X#  OUTPUT FORMAT:  Mtf writes a mapped tar archive to the stdout.
  100. X#  When finished, it leaves a file called "map.report" in the current
  101. X#  directory which records what filenames were mapped and how.  Rename
  102. X#  and save this file, and use it as the "reportfile" argument to any
  103. X#  subsequent runs of mtf in this same directory.  Even if you don't
  104. X#  plan to run mtf again, this file should still be examined, just to
  105. X#  be sure that the new filenames are acceptable, and to see if
  106. X#  perhaps additional .extensions and/or exceptions should be
  107. X#  specified.
  108. X#
  109. X#  BUGS:  Mtf only maps filenames found in the main tar headers.
  110. X#  Because of this, mtf cannot accept nested tar archives.  If you try
  111. X#  to map a tar archive within a tar file, mtf will abort with a nasty
  112. X#  message about screwing up your files.  Please note that, unless you
  113. X#  give mtf a "reportfile" to consider, it knows nothing about files
  114. X#  existing outside the archive.  Hence, if an input archive refers to
  115. X#  an overlong filename in another archive, mtf naturally will not
  116. X#  know to shorten it.  Mtf will, in fact, have no way of knowing that
  117. X#  it is a filename, and not, say, an identifier in a C program.
  118. X#  Final word of caution:  Try not to use mtf on binaries.  It cannot
  119. X#  possibly preserve the correct format and alignment of strings in an
  120. X#  executable.  Same goes for compressed files.  Mtf can't map
  121. X#  filenames that it can't read!
  122. X#
  123. X####################################################################
  124. X
  125. X
  126. Xglobal filenametbl, chunkset, short_chunkset   # see procedure mappiece(s)
  127. Xglobal extensions, no_nos                      # ditto
  128. X
  129. Xrecord hblock(name,junk,size,mtime,chksum,     # tar header struct;
  130. X              linkflag,linkname,therest)       # see readtarhdr(s)
  131. X
  132. X
  133. Xprocedure main(a)
  134. X
  135. X    usage := "usage:  mtf inputfile [-r reportfile] " ||
  136. X         "[-e .extensions] [-x exceptions]"
  137. X
  138. X    *a = 0 & stop(usage)
  139. X
  140. X    intext := open_input_file(a[1]) & pop(a)
  141. X
  142. X    i := 0
  143. X    extensions := []; no_nos := []
  144. X    while (i +:= 1) <= *a do {
  145. X    case a[i] of {
  146. X        "-r"    :    readin_old_map_report(a[i+:=1])
  147. X        "-e"    :    current_list := extensions
  148. X        "-x"    :    current_list := no_nos
  149. X        default :    put(current_list,a[i])
  150. X    }
  151. X    }
  152. X
  153. X    every !extensions ?:= (=".", tab(0))
  154. X    
  155. X    # Run through all the headers in the input file, filling
  156. X    # (global) filenametbl with the names of overlong files;
  157. X    # make_table_of_filenames fails if there are no such files.
  158. X    make_table_of_filenames(intext) | {
  159. X    write(&errout,"mtf:  no overlong path names to map") 
  160. X    a[1] ? (tab(find(".tar")+4), pos(0)) |
  161. X      write(&errout,"(Is ",a[1]," even a tar archive?)")
  162. X     exit(1)
  163. X    } 
  164. X
  165. X    # Now that a table of overlong filenames exists, go back
  166. X    # through the text, remapping all occurrences of these names
  167. X    # to new, 14-char values; also, reset header checksums, and
  168. X    # reformat text into correctly padded 512-byte blocks.  Ter-
  169. X    # minate output with 512 nulls.
  170. X    seek(intext,1)
  171. X    every writes(output_mapped_headers_and_texts(intext))
  172. X
  173. X    close(intext)
  174. X    write_report()   # Record mapped file and dir names for future ref.
  175. X    exit(0)
  176. X    
  177. Xend
  178. X
  179. X
  180. X
  181. Xprocedure open_input_file(s)
  182. X    intext := open("" ~== s,"r") |
  183. X    stop("mtf:  can't open ",s)
  184. X    find("UNIX",&features) |
  185. X    stop("mtf:  I'm not tested on non-Unix systems.")
  186. X    s[-2:0] == ".Z" &
  187. X        stop("mtf:  sorry, can't accept compressed files")
  188. X    return intext
  189. Xend
  190. X
  191. X
  192. X
  193. Xprocedure readin_old_map_report(s)
  194. X
  195. X    initial {
  196. X    filenametbl := table()
  197. X    chunkset := set()
  198. X    short_chunkset := set()
  199. X    }
  200. X
  201. X    mapfile := open_input_file(s)
  202. X    while line := read(mapfile) do {
  203. X    line ? {    
  204. X        if chunk := tab(many(~' \t')) & tab(upto(~' \t')) &
  205. X        lchunk := move(14) & pos(0) then {
  206. X        filenametbl[chunk] := lchunk
  207. X        insert(chunkset,chunk)
  208. X        insert(short_chunkset,chunk[1:16])
  209. X        }
  210. X    if /chunk | /lchunk
  211. X    then stop("mtf:  report file, ",s," seems mangled.")
  212. X    }
  213. X    }
  214. X
  215. Xend
  216. X
  217. X
  218. X
  219. Xprocedure make_table_of_filenames(intext)
  220. X
  221. X    local header # chunkset is global
  222. X
  223. X    # search headers for overlong filenames; for now
  224. X    # ignore everything else
  225. X    while header := readtarhdr(reads(intext,512)) do {
  226. X    # tab upto the next header block
  227. X    tab_nxt_hdr(intext,trim_str(header.size),1)
  228. X    # record overlong filenames in several global tables, sets
  229. X    fixpath(trim_str(header.name))
  230. X    }
  231. X    *\chunkset ~= 0 | fail
  232. X    return &null
  233. X
  234. Xend
  235. X
  236. X
  237. X
  238. Xprocedure output_mapped_headers_and_texts(intext)
  239. X
  240. X    # Remember that filenametbl, chunkset, and short_chunkset
  241. X    # (which are used by various procedures below) are global.
  242. X    local header, newtext, full_block, block, lastblock
  243. X
  244. X    # Read in headers, one at a time.
  245. X    while header := readtarhdr(reads(intext,512)) do {
  246. X
  247. X    # Replace overlong filenames with shorter ones, according to
  248. X    # the conversions specified in the global hash table filenametbl
  249. X    # (which were generated by fixpath() on the first pass).
  250. X          header.name := left(map_filenams(header.name),100,"\x00")
  251. X    header.linkname := left(map_filenams(header.linkname),100,"\x00")
  252. X
  253. X    # Use header.size field to determine the size of the subsequent text.
  254. X    # Read in the text as one string.  Map overlong filenames found in it
  255. X     # to shorter names as specified in the global hash table filenamtbl.
  256. X    newtext := map_filenams(tab_nxt_hdr(intext,trim_str(header.size)))
  257. X
  258. X    # Now, find the length of newtext, and insert it into the size field.
  259. X    header.size := right(exbase10(*newtext,8) || " ",12," ")
  260. X
  261. X    # Calculate the checksum of the newly retouched header.
  262. X    header.chksum := right(exbase10(get_checksum(header),8)||"\x00 ",8," ")
  263. X
  264. X    # Finally, join all the header fields into a new block and write it out
  265. X    full_block := ""; every full_block ||:= !header
  266. X    suspend left(full_block,512,"\x00")
  267. X
  268. X    # Now we're ready to write out the text, padding the final block
  269. X    # out to an even 512 bytes if necessary; the next header must start
  270. X    # right at the beginning of a 512-byte block.
  271. X    newtext ? {
  272. X        while block := move(512)
  273. X        do suspend block
  274. X        pos(0) & next
  275. X            lastblock := left(tab(0),512,"\x00")
  276. X        suspend lastblock
  277. X    }
  278. X    }
  279. X    # Write out a final null-filled block.  Some tar programs will write
  280. X    # out 1024 nulls at the end.  Dunno why.
  281. X    return repl("\x00",512)
  282. X
  283. Xend
  284. X
  285. X
  286. X
  287. Xprocedure trim_str(s)
  288. X
  289. X    # Knock out spaces, nulls from those crazy tar header
  290. X    # block fields (some of which end in a space and a null,
  291. X    # some just a space, and some just a null [anyone know
  292. X    # why?]).
  293. X    return s ? {
  294. X    (tab(many(' ')) | &null) &
  295. X        trim(tab(find("\x00")|0))
  296. X    } \ 1
  297. X
  298. Xend 
  299. X
  300. X
  301. X
  302. Xprocedure tab_nxt_hdr(f,size_str,firstpass)
  303. X
  304. X    # Tab upto the next header block.  Return the bypassed text
  305. X    # as a string if not the first pass.
  306. X
  307. X    local hs, next_header_offset
  308. X
  309. X    hs := integer("8r" || size_str)
  310. X    next_header_offset := (hs / 512) * 512
  311. X    hs % 512 ~= 0 & next_header_offset +:= 512
  312. X    if 0 = next_header_offset then return ""
  313. X    else {
  314. X    # if this is pass no. 1 don't bother returning a value; we're
  315. X    # just collecting long filenames;
  316. X    if \firstpass then {
  317. X        seek(f,where(f)+next_header_offset)
  318. X        return
  319. X    }
  320. X    else {
  321. X        return reads(f,next_header_offset)[1:hs+1] |
  322. X        stop("mtf:  error reading in ",
  323. X             string(next_header_offset)," bytes.")
  324. X    }
  325. X    }
  326. X
  327. Xend
  328. X
  329. X
  330. X
  331. Xprocedure fixpath(s)
  332. X
  333. X    # Fixpath is a misnomer of sorts, since it is used on
  334. X    # the first pass only, and merely examines each filename
  335. X    # in a path, using the procedure mappiece to record any
  336. X    # overlong ones in the global table filenametbl and in
  337. X    # the global sets chunkset and short_chunkset; no fixing
  338. X    # is actually done here.
  339. X
  340. X    s2 := ""
  341. X    s ? {
  342. X    while piece := tab(find("/")+1)
  343. X    do s2 ||:= mappiece(piece) 
  344. X    s2 ||:= mappiece(tab(0))
  345. X    }
  346. X    return s2
  347. X
  348. Xend
  349. X
  350. X
  351. X
  352. Xprocedure mappiece(s)
  353. X
  354. X    # Check s (the name of a file or dir as recorded in the tar header
  355. X    # being examined) to see if it is over 14 chars long.  If so,
  356. X    # generate a unique 14-char version of the name, and store
  357. X    # both values in the global hashtable filenametbl.  Also store
  358. X    # the original (overlong) file name in chunkset.  Store the
  359. X    # first fifteen chars of the original file name in short_chunkset.
  360. X    # Sorry about all of the tables and sets.  It actually makes for
  361. X    # a reasonably efficient program.  Doing away with both sets,
  362. X    # while possible, causes a tenfold drop in execution speed!
  363. X    
  364. X    # global filenametbl, chunkset, short_chunkset, extensions
  365. X    local j, ending
  366. X
  367. X    initial {
  368. X    /filenametbl := table()
  369. X    /chunkset := set()
  370. X    /short_chunkset := set()
  371. X    }
  372. X   
  373. X    chunk := trim(s,'/')
  374. X    if chunk ? (tab(find(".tar")+4), pos(0)) then {
  375. X    write(&errout, "mtf:  Sorry, I can't let you do this.\n",
  376. X                   "      You've nested a tar archive within\n",
  377. X                   "      another tar archive, which makes it\n",
  378. X                   "      likely I'll f your filenames ubar.")
  379. X    exit(2)
  380. X    }
  381. X    if *chunk > 14 then {
  382. X    i := 0
  383. X
  384. X    if /filenametbl[chunk] then {
  385. X    # if we have not seen this file, then...
  386. X        repeat {
  387. X        # ...find a new unique 14-character name for it;
  388. X        # preserve important suffixes like ".Z," ".c," etc.
  389. X        # First, check to see if the original filename (chunk)
  390. X        # ends in an important extension...
  391. X        if chunk ?
  392. X            (tab(find(".")),
  393. X             ending := move(1) || tab(match(!extensions)|any(&ascii)),
  394. X             pos(0)
  395. X             )
  396. X        # ...If so, then leave the extension alone; mess with the
  397. X        # middle part of the filename (e.g. file.with.extension.c ->
  398. X        # file.with001.c).
  399. X        then {
  400. X            j := (15 - *ending - 3)
  401. X            lchunk:= chunk[1:j] || right(string(i+:=1),3,"0") || ending
  402. X        }
  403. X        # If no important extension is present, then reformat the
  404. X        # end of the file (e.g. too.long.file.name -> too.long.fi01).
  405. X        else lchunk := chunk[1:13] || right(string(i+:=1),2,"0")
  406. X
  407. X        # If the resulting shorter file name has already been used...
  408. X        if lchunk == !filenametbl
  409. X        # ...then go back and find another (i.e. increment i & try
  410. X        # again; else break from the repeat loop, and...
  411. X        then next else break
  412. X        }
  413. X            # ...record both the old filename (chunk) and its new,
  414. X        # mapped name (lchunk) in filenametbl.  Also record the
  415. X        # mapped names in chunkset and short_chunkset.
  416. X        filenametbl[chunk] := lchunk
  417. X        insert(chunkset,chunk)
  418. X        insert(short_chunkset,chunk[1:16])
  419. X    }
  420. X    }
  421. X
  422. X    # If the filename is overlong, return lchunk (the shortened
  423. X    # name), else return the original name (chunk).  If the name,
  424. X    # as passed to the current function, contained a trailing /
  425. X    # (i.e. if s[-1]=="/"), then put the / back.  This could be
  426. X    # done more elegantly.
  427. X    return (\lchunk | chunk) || ((s[-1] == "/") | "")
  428. X
  429. Xend
  430. X
  431. X
  432. X
  433. Xprocedure readtarhdr(s)
  434. X
  435. X    # Read the silly tar header into a record.  Note that, as was
  436. X    # complained about above, some of the fields end in a null, some
  437. X    # in a space, and some in a space and a null.  The procedure
  438. X    # trim_str() may (and in fact often _is_) used to remove this
  439. X    # extra garbage.
  440. X
  441. X    this_block := hblock()
  442. X    s ? {
  443. X    this_block.name     := move(100)    # <- to be looked at later
  444. X    this_block.junk     := move(8+8+8)  # skip the permissions, uid, etc.
  445. X    this_block.size     := move(12)     # <- to be looked at later
  446. X    this_block.mtime    := move(12)
  447. X    this_block.chksum   := move(8)      # <- to be looked at later
  448. X    this_block.linkflag := move(1)
  449. X    this_block.linkname := move(100)    # <- to be looked at later
  450. X    this_block.therest  := tab(0)
  451. X    }
  452. X    integer(this_block.size) | fail  # If it's not an integer, we've hit
  453. X                                     # the final (null-filled) block.
  454. X    return this_block
  455. X
  456. Xend
  457. X
  458. X
  459. X
  460. Xprocedure map_filenams(s)
  461. X
  462. X    # Chunkset is global, and contains all the overlong filenames
  463. X    # found in the first pass through the input file; here the aim
  464. X    # is to map these filenames to the shortened variants as stored
  465. X    # in filenametbl (GLOBAL).
  466. X
  467. X    local s2, tmp_chunk_tbl, tmp_lst
  468. X    static new_chunklist
  469. X    initial {
  470. X
  471. X        # Make sure filenames are sorted, longest first.  Say we
  472. X        # have a file called long_file_name_here.1 and one called
  473. X        # long_file_name_here.1a.  We want to check for the longer
  474. X        # one first.  Otherwise the portion of the second file which
  475. X        # matches the first file will get remapped.
  476. X        tmp_chunk_tbl := table()
  477. X        every el := !chunkset
  478. X        do insert(tmp_chunk_tbl,el,*el)
  479. X        tmp_lst := sort(tmp_chunk_tbl,4)
  480. X        new_chunklist := list()
  481. X        every put(new_chunklist,tmp_lst[*tmp_lst-1 to 1 by -2])
  482. X
  483. X    }
  484. X
  485. X    s2 := ""
  486. X    s ? {
  487. X    until pos(0) do {
  488. X        # first narrow the possibilities, using short_chunkset
  489. X        if member(short_chunkset,&subject[&pos:&pos+15])
  490. X            # then try to map from a long to a shorter 14-char filename
  491. X        then {
  492. X        if match(ch := !new_chunklist) & not match(!no_nos)
  493. X        then s2 ||:= filenametbl[=ch]
  494. X        else s2 ||:= move(1)
  495. X        }
  496. X        else s2 ||:= move(1)
  497. X    }
  498. X    }
  499. X    return s2
  500. X
  501. Xend
  502. X
  503. X
  504. X#  From the IPL.  Thanks, Ralph -
  505. X#  Author:  Ralph E. Griswold
  506. X#  Date:  June 10, 1988
  507. X#  exbase10(i,j) convert base-10 integer i to base j
  508. X#  The maximum base allowed is 36.
  509. X
  510. Xprocedure exbase10(i,j)
  511. X
  512. X   static digits
  513. X   local s, d, sign
  514. X   initial digits := &digits || &lcase
  515. X   if i = 0 then return 0
  516. X   if i < 0 then {
  517. X      sign := "-"
  518. X      i := -i
  519. X      }
  520. X   else sign := ""
  521. X   s := ""
  522. X   while i > 0 do {
  523. X      d := i % j
  524. X      if d > 9 then d := digits[d + 1]
  525. X      s := d || s
  526. X      i /:= j
  527. X      }
  528. X   return sign || s
  529. X
  530. Xend
  531. X
  532. X# end IPL material
  533. X
  534. X
  535. Xprocedure get_checksum(r)
  536. X    # Calculates the new value of the checksum field for the
  537. X    # current header block.  Note that the specification say
  538. X    # that, when calculating this value, the chksum field must
  539. X    # be blank-filled.
  540. X
  541. X    sum := 0
  542. X    r.chksum := "        "
  543. X    every field := !r
  544. X    do every sum +:= ord(!field)
  545. X    return sum
  546. X
  547. Xend
  548. X
  549. X
  550. X
  551. Xprocedure write_report()
  552. X
  553. X    # This procedure writes out a list of filenames which were
  554. X    # remapped (because they exceeded the SysV 14-char limit),
  555. X    # and then notifies the user of the existence of this file.
  556. X
  557. X    local outtext, stbl, i, j, mapfile_name
  558. X
  559. X    # Get a unique name for the map.report (thereby preventing
  560. X    # us from overwriting an older one).
  561. X    mapfile_name := "map.report"; j := 1
  562. X    until not close(open(mapfile_name,"r"))
  563. X    do mapfile_name := (mapfile_name[1:11] || string(j+:=1))
  564. X
  565. X    (outtext := open(mapfile_name,"w")) |
  566. X    open(mapfile_name := "/tmp/map.report","w") |
  567. X         stop("mtf:  Can't find a place to put map.report!")
  568. X    stbl := sort(filenametbl,3)
  569. X    every i := 1 to *stbl -1 by 2 do {
  570. X    match(!no_nos,stbl[i]) |
  571. X        write(outtext,left(stbl[i],35," ")," ",stbl[i+1])
  572. X    }
  573. X    write(&errout,"\nmtf:  ",mapfile_name," contains the list of changes.")
  574. X    write(&errout,"      Please save this list!")
  575. X    close(outtext)
  576. X    return &null
  577. X
  578. Xend
  579. SHAR_EOF
  580. true || echo 'restore of mtf.icn failed'
  581. rm -f _shar_wnt_.tmp
  582. fi
  583. # ============= README ==============
  584. if test -f 'README' -a X"$1" != X"-c"; then
  585.     echo 'x - skipping README (File already exists)'
  586.     rm -f _shar_wnt_.tmp
  587. else
  588. > _shar_wnt_.tmp
  589. echo 'x - extracting README (Text)'
  590. sed 's/^X//' << 'SHAR_EOF' > 'README' &&
  591. XNAME:  mtf
  592. X
  593. XLANGUAGE:  Icon
  594. X
  595. XAUTHOR:  Richard Goerwitz (goer@sophist.uchicago.edu)
  596. X
  597. XPURPOSE:  Maps 15+ char. filenames in a tar archive to 14 chars.
  598. XHandles both header blocks and the archive itself.  Mtf is intended to
  599. Xfacilitate installation of tar'd archives on systems subject to a
  600. X14-character filename limit.
  601. X
  602. XINSTALLATION:  Cp Makefile.dist to Makefile and make.  If all goes
  603. Xwell, and you have root priviledges, edit the Makefile to reflect
  604. Xyour local file structure, and make install.
  605. X
  606. XUSAGE:  mtf inputfile [-r reportfile] [-e .extensions] [-x exceptions]
  607. X
  608. X"Inputfile" is a tar archive.  "Reportfile" is file containing a list
  609. Xof files already mapped by mtf in a previous run (used to avoid
  610. Xclashes with filenames in use outside the current archive).  The -e
  611. Xswitch precedes a list of filename .extensions which mtf is supposed
  612. SHAR_EOF
  613. true || echo 'restore of README failed'
  614. fi
  615. echo 'End of  part 1'
  616. echo 'File README is continued in part 2'
  617. echo 2 > _shar_seq_.tmp
  618. exit 0
  619.  
  620. exit 0 # Just in case...
  621. -- 
  622. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  623. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  624. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  625. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  626.